""" _*_ coding : utf-8 _*_
 @Time: 2025/7/25 19:34
 @Author : 虎
 @File : urls
 @Project : fastApiProject
"""
from fastapi import APIRouter
from pydantic import BaseModel
from fastapi import APIRouter, HTTPException
from apps.models import User, Token, Role
from datetime import datetime, timedelta
import secrets
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from fastapi import status
from passlib.context import CryptContext
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, EmailStr, validator
from datetime import datetime, timedelta
import random
import string
from typing import Dict
from aiosmtplib import SMTP
from email_validator import validate_email, EmailNotValidError
from email.mime.text import MIMEText
from jinja2 import Template

import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

user = APIRouter()
# 内存存储验证码（生产环境建议使用Redis）
verification_codes: Dict[str, dict] = {}


# 登录请求模型
class LoginRequest(BaseModel):
    username: str
    password: str
    # 接受角色
    role: str
    #email
    email: EmailStr



# 响应模型
class TokenResponse(BaseModel):
    access_token: str
    token_type: str = "bearer"
    expires_at: datetime


# 密码哈希验证工具函数
async def verify_password(plain_password: str, hashed_password: str):
    # 实际项目中应使用密码哈希库（如 passlib）
    return plain_password == hashed_password  # 示例简化，生产环境必须替换！


# 生成Token
async def create_access_token(user_id: int):
    # 生成随机Token（实际项目可用JWT）
    token = secrets.token_urlsafe(32)
    expires_at = datetime.now() + timedelta(days=7)

    # 存储到数据库
    await Token.create(
        token=token,
        user_id=user_id,
        expires_at=expires_at,
        is_active=True
    )
    return token, expires_at


@user.post("/api/register")
async def register(register_data: LoginRequest):
    user = await User.get_or_none(username=register_data.username)
    role = await Role.get_or_none(name=register_data.role)

    if not role:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="角色不存在"
        )

    if user:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="用户已存在"
        )

    hashed_password = pwd_context.hash(register_data.password)
    await User.create(username=register_data.username, password=hashed_password, role=role)

    return {
        "message": "注册成功"
    }  # 成功时不需要返回code，HTTP 200状态码已表示成功


# 登录接口
@user.post("/api/login", response_model=dict)
async def login(login_data: LoginRequest):
    print(f"收到登录请求: {login_data}")
    # 查询用户
    user = await User.get_or_none(username=login_data.username).select_related("role")

    if not user:
        raise HTTPException(status_code=400, detail="用户不存在")

    # 验证密码（生产环境必须使用哈希！）
    if not await verify_password(login_data.password, user.password):
        raise HTTPException(status_code=400, detail="密码错误")
    if user.role.name != login_data.role:
        raise HTTPException(status_code=400, detail="用户角色错误")
    # 生成并存储Token
    token, expires_at = await create_access_token(user.id)

    # 返回结果
    return {
        "code": 200,
        "message": "登录成功",
        "data": {
            "token": token,
            "expires_at": expires_at.isoformat(),
            "user_info": {
                "id": user.id,
                "username": user.username
            }
        }
    }





# 更新SMTP配置（推荐使用465端口+SSL）
SMTP_CONFIG = {
    "hostname": "smtp.qq.com",
    "port": 587,  # 使用465端口
    "username": "434491214@qq.com",  # 替换为你的QQ邮箱
    "password": "cqzsvtppgumjbiih",  # SMTP授权码
    "timeout": 10,
    "use_tls": False,  # 465端口不需要TLS
    "start_tls": False,  # 禁用STARTTLS
}


# 请求模型
# 请求模型
class SendCodeRequest(BaseModel):
    email: str

    @validator('email')
    def validate_email(cls, v):
        try:
            emailinfo = validate_email(v, check_deliverability=False)
            return emailinfo.normalized
        except EmailNotValidError:
            raise ValueError("无效的邮箱地址")


class VerifyCodeRequest(BaseModel):
    email: str
    code: str


# 邮件模板
EMAIL_TEMPLATE = Template("""
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>邮箱验证码</title>
</head>
<body>
    <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
        <h2 style="color: #409EFF;">智慧教育云平台 - 邮箱验证</h2>
        <p>您的验证码是：</p>
        <div style="text-align: center; margin: 20px 0;">
            <span style="display: inline-block; padding: 10px 20px; 
                        background-color: #409EFF; color: white; 
                        font-size: 24px; font-weight: bold; 
                        border-radius: 4px;">
                {{ code }}
            </span>
        </div>
        <p>验证码有效期为10分钟，请勿泄露给他人。</p>
        <hr>
        <p style="font-size: 12px; color: #909399;">
            此为系统邮件，请勿直接回复
        </p>
    </div>
</body>
</html>
""")

# # 邮件模板
# EMAIL_TEMPLATE = Template("""<!DOCTYPE html>
# <html>
# <head><meta charset="UTF-8"><title>邮箱验证码</title></head>
# <body>
# <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
#     <h2 style="color: #409EFF;">验证码通知</h2>
#     <p>您的验证码是：</p>
#     <div style="text-align: center; margin: 20px 0;">
#         <span style="display: inline-block; padding: 10px 20px;
#                     background-color: #409EFF; color: white;
#                     font-size: 24px; font-weight: bold;
#                     border-radius: 4px;">{{ code }}</span>
#     </div>
#     <p>验证码有效期为10分钟，请勿泄露给他人。</p>
#     <hr>
#     <p style="font-size: 12px; color: #909399;">此为系统邮件，请勿直接回复</p>
# </div>
# </body>
# </html>""")


async def send_email(to_email: str, subject: str, content: str) -> bool:
    msg = MIMEText(content, 'html', 'utf-8')
    # 关键修改：使用简单邮箱地址格式（去掉显示名称）
    msg['From'] = SMTP_CONFIG["username"]  # 直接使用邮箱地址
    msg['To'] = to_email
    msg['Subject'] = subject

    smtp = None
    try:
        # 创建SMTP连接（使用SSL）
        smtp = SMTP(
            hostname=SMTP_CONFIG["hostname"],
            port=SMTP_CONFIG["port"],
            use_tls=SMTP_CONFIG["use_tls"],
            timeout=SMTP_CONFIG["timeout"],
        )

        logger.info(f"尝试连接SMTP服务器: {SMTP_CONFIG['hostname']}:{SMTP_CONFIG['port']}")
        await smtp.connect()

        if not smtp.is_connected:
            logger.error("SMTP连接失败")
            return False

        logger.info("SMTP连接成功，尝试登录...")
        await smtp.login(
            SMTP_CONFIG["username"],
            SMTP_CONFIG["password"]
        )

        logger.info("登录成功，发送邮件...")
        await smtp.send_message(msg)
        logger.info(f"邮件发送成功: {to_email}")
        return True

    except Exception as e:
        logger.error(f"邮件发送失败: {str(e)}", exc_info=True)
        return False
    finally:
        if smtp and smtp.is_connected:
            try:
                await smtp.quit()
                logger.info("SMTP连接已关闭")
            except Exception as e:
                logger.warning(f"关闭连接时出错: {str(e)}")


@user.post("/send-verification-code")
async def send_verification_code(request: SendCodeRequest):
    """发送验证码接口"""
    email = request.email

    # 频率限制检查（60秒内只能发送一次）
    if email in verification_codes:
        last_sent = verification_codes[email]["created_at"]
        if datetime.now() - last_sent < timedelta(seconds=60):
            raise HTTPException(
                status_code=429,
                detail="操作过于频繁，请60秒后再试",
                headers={"Retry-After": "60"}
            )

    # 生成6位数字验证码
    code = ''.join(random.choices(string.digits, k=6))
    verification_codes[email] = {
        "code": code,
        "created_at": datetime.now(),
        "verified": False
    }

    # 发送邮件
    email_content = EMAIL_TEMPLATE.render(code=code)
    success = await send_email(
        to_email=email,
        subject="您的验证码",
        content=email_content
    )

    if not success:
        del verification_codes[email]
        raise HTTPException(
            status_code=500,
            detail="邮件发送失败，请检查邮箱地址或稍后重试"
        )
    print(verification_codes)

    return {"code": 200, "message": "验证码已发送"}


@user.post("/verify-email-code")
async def verify_email_code(request: VerifyCodeRequest):
    """验证验证码接口"""
    email = request.email
    code = request.code

    # 检查验证码是否存在
    if email not in verification_codes:
        raise HTTPException(status_code=400, detail="请先获取验证码")

    # 检查验证码有效期（10分钟）
    verification_data = verification_codes[email]
    if datetime.now() - verification_data["created_at"] > timedelta(minutes=10):
        del verification_codes[email]
        raise HTTPException(status_code=400, detail="验证码已过期")

    # 验证码比对
    if verification_data["code"] != code:
        raise HTTPException(status_code=400, detail="验证码错误")

    # 标记为已验证
    verification_codes[email]["verified"] = True
    return {"code": 200, "message": "验证成功"}


@user.post("/check-email-verified")
async def check_email_verified(email: str):
    """检查验证状态接口"""
    if email not in verification_codes or not verification_codes[email]["verified"]:
        raise HTTPException(status_code=400, detail="邮箱未验证")
    return {"code": 200, "message": "邮箱已验证"}


